<?php
use Workerman\Worker;
use \GatewayWorker\Lib\Gateway;
//use \GatewayWorker\Lib\Db;

require_once 'vendor/autoload.php';
require_once 'db/Db.php';

// 初始化一个worker容器，监听2700端口
$worker = new Worker('tcp://0.0.0.0:2700');

global $worker;
// 新增加一个属性，用来保存uid到connection的映射
$worker->uidConnections = array();

// worker进程启动后创建一个text Worker以便打开一个内部通讯端口
$worker->onWorkerStart = function ($worker) {
    //开启一个内部端口，方便内部系统推送数据，Text协议格式 文本+换行符
    $inner_text_worker            = new Worker('text://0.0.0.0:2701');
    $inner_text_worker->onMessage = function ($connection, $data) {
        // $data数组格式，里面有uid，表示向那个uid的页面推送数据
        $param    = json_decode($data, true);
        $deviceId = $param['id'];
        // 通过workerman，向uid的页面推送数据
        $ret = sendMessageByUid($deviceId, iconv("UTF-8", "gb2312//IGNORE", $data));
        // 返回推送结果
        $connection->send($ret ? 'ok' : 'fail');
    };
    // ## 执行监听 ##
    $inner_text_worker->listen();
};

//当连接建立时触发
$worker->onConnect = function ($connection) {
    $connection->send('Connect success');
};

// 当有客户端发来消息时执行的回调函数
$worker->onMessage = function ($connection, $data) {
    global $worker;
    $db = new Config\Db();
    // 判断当前客户端是否已经验证,既是否设置了uid
    if (!isset($connection->uid)) {
        // 没验证的话把第一个包当做uid（这里为了方便演示，没做真正的验证）
//				$connection->uid = $data;
//				/* 保存uid到connection的映射，这样可以方便的通过uid查找connection，
//                 * 实现针对特定uid推送数据
//                 */
//				$worker->uidConnections[$connection->uid] = $connection;
//				$connection->send(var_dump($connection->uid));
        $data  = '{"id":"356566070698642"}';
        $param = json_decode($data, true);
        if (!isset($param['id']) || empty($param['id'])) {
            $connection->close("device id can not be null!");
            return;
        }

        $deviceInfo = $db->getDeviceInfo($param['id']);
        if (empty($deviceInfo)) {
            $connection->close("this device not found!");
            return;
        }

        //上报地理位置
        if ($param['id'] && (isset($param['lng']) && !empty($param['lng'])) && (isset($param['lat']) && !empty($param['lat']))) {
            $deviceInfo = $db->getUidByDeviceId($param['id']);
            if (empty($deviceInfo['uid'])) {
                $connection->send(iconv("UTF-8", "gb2312//IGNORE", json_encode(["msg" => "查无该设备"], JSON_UNESCAPED_UNICODE)));
                return;
            }
            $lngLatData = [
                'uid'       => $deviceInfo['uid'],    //用户id
                'device_id' => $param['id'],    //设备id
                'longitude' => $param['lng'],    //经度
                'latitude'  => $param['lat'],    //纬度
            ];
            $insertId   = $db->insertLongLat($lngLatData);    //经纬度入库
            if (empty($insertId)) {
                $connection->send(iconv("UTF-8", "gb2312//IGNORE", json_encode(["msg" => "上报地理位置错误"], JSON_UNESCAPED_UNICODE)));
                return;
            }
            $connection->send(iconv("UTF-8", "gb2312//IGNORE", json_encode(["msg" => "成功"], JSON_UNESCAPED_UNICODE)));
            return;
        } else {    //连接成功后第一次发送数据返回信息
            $worker->uidConnections[$param['id']] = $connection;
            $connection->send(iconv("UTF-8", "gb2312//IGNORE", json_encode(["msg" => "车途宝已准备就绪..."], JSON_UNESCAPED_UNICODE)));
            return;
        }
    }
};

// 当有客户端连接断开时
$worker->onClose = function ($connection) {
    global $worker;
    if (isset($connection->id)) {
        // 连接断开时删除映射
        unset($worker->uidConnections[$connection->id]);
    }
};

// 运行worker
Worker::runAll();

// 向所有验证的用户推送数据
function broadcast($message)
{
    global $worker;
    foreach ($worker->uidConnections as $connection) {
        $connection->send($message);
    }
}

// 针对uid推送数据
function sendMessageByUid($uid, $message)
{
    global $worker;
    if (isset($worker->uidConnections[$uid])) {
        $connection = $worker->uidConnections[$uid];
        $connection->send($message);
        return true;
    }
    return false;
}

